package main

import (
	"bufio"
	"bytes"
	"fmt"
	"strings"
)

func main() {
	/*
		3.type Write
		（1）基础介绍：
			bufio.Writer 是 bufio 中对 io.Writer 的封装
				type Writer struct {
					err error
					buf []byte
					n   int
					wr  io.Writer
				}

			bufio.Write(p []byte) 的思路：
			1.判断 buf 中可用容量是否可以放下 p
			2.如果能放下，直接把 p 拼接到 buf 后面，即把内容放到缓冲区
			3.如果缓冲区的可用容量不足以放下，且此时缓冲区是空的，直接把 p 写入文件即可
			4.如果缓冲区的可用容量不足以放下，且此时缓冲区有内容，则用 p 把缓冲区填满，把缓冲区所有内容写入文件，并清空缓冲区
			5.判断 p 的剩余内容大小能否放到缓冲区，如果能放下（此时和步骤1情况一样）则把内容放到缓冲区
			6.如果 p 的剩余内容依旧大于缓冲区，（注意此时缓冲区是空的，情况和步骤 3 一样）则把 p 的剩余内容直接写入文件

		（2）方法
			1.func NewWriter(w io.Writer) *Writer
				创建一个具有默认大小缓冲、写入 w 的 *Writer。
				相当于 NewWriterSize(wr, 4096)

			2.func NewWriterSize(w io.Writer, size int) *Writer
				创建一个具有最少有 size 尺寸的缓冲、写入 w 的 Writer。
				如果参数 w 已经是一个具有足够大缓冲的 Writer 类型值，会返回 w。

			3.func (b *Writer) Reset(w io.Writer)
				丢弃缓冲中的数据，清除任何错误，将 b 重设为 将其输出写入 w
				本来 b 会将它的输出写入 另一个 io.Writer 类型的变量，但是现在会将它的输出写入 io.Writer类型的变量 w

			注：该方法并不会关闭之前与 Writer 对象关联的 io.Writer 对象（如果有的话），因此在调用该方法前应该手动关闭该对象。

			4.func (b *Writer) Buffered() int
				返回缓冲中已使用的字节数

			5.func (b *Writer) Available() int
				返回缓冲中还有多少字节未使用

			6.func (b *Writer) Write(p []byte) (nn int, err error)
				将 p 的内容写入缓冲。
				返回写入的字节数。
				如果返回值 nn < len(p)，还会返回一个错误说明原因。

			7.func (b *Writer) WriterString(s string) (int, error)
				写入一个字符串。
				返回写入的字节数。
				如果返回值 m < len(s)，还会返回一个错误说明原因。

			8.func (b *Writer) WriteByte(c byte) error
				写入单个字节

			9.func (b *Writer) WriterRune(r rune) (size int, err error)
				写入一个unicode码值（的UTF-8编码），返回写入的字节数、可能的错误

			10.func (b* Writer) Flush() error
				将缓冲中的数据写入下层的 io.Writer 接口

			11.func (b *Writer) ReadFrom(r io.Reader) (n int64, err error)
				实现了 io.ReaderFrom 接口

		4.type ReadWriter
		（1）基础介绍：
			ReadWriter 类型保管了指向 Reader 和 Writer 类型的指针，（因此）实现了 io.ReadWriter 接口。
				type ReadWriter struct {
					*Reader
					*Writer
				}

		（2）方法：
			1.func NewReadWriter(r *Reader, w *Writer) *ReadWriter
				申请创建一个新的、将读写操作分派给 r 和 w 的 ReadWriter。

	*/
	//NewWriter、Reset
	b := bytes.NewBuffer(make([]byte, 0)) //创建一个新的字节缓冲区 bytes.Buffer 类型以及网络连接 斗实现了 io.Writer 接口
	bw := bufio.NewWriter(b)
	bw.WriteString("123456789")
	c := bytes.NewBuffer(make([]byte, 0))
	bw.Reset(c)
	bw.WriteString("456")
	bw.Flush()           //将缓冲中的数据写入 c 接口
	fmt.Println("b:", b) //b:
	fmt.Println("c:", c) //c: 456

	fmt.Println("-----------------------------------")

	//ReadFrom
	//实例一
	b1 := bytes.NewBuffer(make([]byte, 0))
	bw1 := bufio.NewWriter(b1)
	fmt.Println(bw1.Available()) //4096 未使用的字节数
	fmt.Println(bw1.Buffered())  //0 已使用的字节数

	bw1.WriteString("ABCDEFGHIJKLMN")
	fmt.Println(bw1.Available()) //4082
	fmt.Println(bw1.Buffered())  //14
	fmt.Printf("%q\n", b1)       //""

	bw1.Flush()
	fmt.Println(bw1.Available()) //4096
	fmt.Println(bw1.Buffered())  //0
	fmt.Printf("%q\n", b1)       //"ABCDEFGHIJKLMN"

	//实例二
	b3 := bytes.NewBuffer(make([]byte, 0))
	s3 := strings.NewReader("喜羊羊真帅！！！")
	bw3 := bufio.NewWriter(b3)
	bw3.ReadFrom(s3)
	//bw3.Flush() //ReadFrom 无需使用 Flush，其自己已经写入
	fmt.Println(b3) //喜羊羊真帅！！！

	fmt.Println("------------------------------------------------------")

	//ReadWriter
	b4 := bytes.NewBuffer(make([]byte, 0))
	s4 := strings.NewReader("123")
	bw4 := bufio.NewWriter(b4)
	br := bufio.NewReader(s4)
	rw := bufio.NewReadWriter(br, bw4)
	p, _ := rw.ReadString('\n')
	fmt.Println(string(p)) //123
	rw.WriteString("asdf")
	rw.Flush()
	fmt.Println(b4) //asdf

}
